#ifndef C3GUI_H
#define C3GUI_H

#include "c3DisplayObject.h"
#include "c3Events.h"

struct GUIEvent { enum {
  None = 'EGUI',
  Click,
  SelClick,
  DoubleClick,
  KeyClick,
  MouseDown,
  MouseUp
};};

struct GUILoader;

class GUIControl : public DisplayObject
{
public:
  //Image* TheImage;
  GUIControl();
  virtual ~GUIControl() {}
  bool MouseDown(int x, int y);
  bool MouseUp(int x, int y);

  virtual uint Type() const { return 'guic'; }

  void SetDisplay( bool display );
	GUIControl& Set( Image* image, int x, int y );

	virtual void Load(GUILoader& loader);

  static void SetClickSound(Sound* sound);
protected:
  virtual bool OnMouseDown(int x, int y);
  virtual bool OnMouseUp(int x, int y);
  virtual bool OnClick();
  bool mPressed;
};

class Button : public GUIControl
{
public:
	enum ButtonType
	{
		Normal,
		CheckButton,
		RadioButton,
	};

  uint TextColor;

  Button();
  virtual ~Button() {}

  virtual uint Type() const { return 'butt'; }

  void SetType(ButtonType type);
  void SetFont(Font* font);
  void SetLabel(const wchar_t* label);

	void SetActive(bool active) { mActive = active; }
	bool IsActive() const { return mActive; }

  virtual int GetImageState();

	Button& Set(Font& font, Image& image, const wchar_t* label, int x, int y, ButtonType type = Button::Normal);

	ButtonType GetType() const { return mType; }
protected:
  virtual uint DrawAt(int x, int y, uint8 alpha);
  virtual bool OnMouseDown(int x, int y);
  virtual bool OnMouseUp(int x, int y);
  virtual bool OnClick();
  ButtonType mType;
  const wchar_t* mLabel;
  int mLabelLen;
  Font* mFont;

  int mFrame;
	bool mActive;
};

class ImageButton : public Button
{
public:
	virtual uint Type() const { return 'imbu'; }

	ImageButton();
	Image* ButtonImage;

	ImageButton& Set(Image& image, Image* butImage, int x, int y, ButtonType type = Button::Normal);
private:
	virtual uint DrawAt(int x, int y, uint8 alpha);
};

class Selecter : public GUIControl
{
public:
  void Select();
  void Deselect();

  bool IsSelected() const { return mSelected; }

  uint SelectGroup;

  Selecter();
  virtual ~Selecter();

  virtual uint Type() const { return 'sele'; }

  Selecter& Set(uint group, Image& image, int x, int y);
private:
  virtual bool OnClick();

  bool mSelected;
};

class Checker : public GUIControl
{
public:
	void Check();
	void Uncheck();

	bool IsChecked() const { return mChecked; }

	Checker();
	virtual ~Checker();

	virtual uint Type() const { return 'chck'; }

	Checker& Set(Image& image, int x, int y);
private:
	virtual bool OnClick();

	bool mChecked;
};

class Label : public GUIControl
{
public:
  Label();
  virtual ~Label();
  virtual uint Type() const { return 'labl'; }

  uint TextColor;
  int TextAlignment;

  /// Set if you want the text of the label to come from Userdata[0].
  /// Does not work if WordWrap is set to true.
  int UseUserData;

	Label& Set(int x, int y, Font& font, const wchar_t* label, bool wordWrap = false);
  void SetLabel(wchar_t* text);
  void SetFont(Font* font);
  void SetWordWrap(bool wrap, int maxWidth = 0);

  struct UserDataUsage
  {
    enum {
      None = 0,
      Number,
      String,
    };
  };
protected:
  struct Line
  {
    wchar_t* Start;
    uint16 CharLength;
    uint16 PixelLength;
    bool IsWrapped;

    Line() { Reset(); }
    void Reset()
    {
      IsWrapped = false;
      Start = 0;
      CharLength = PixelLength = 0;
    }
  };
  virtual uint DrawAt(int x, int y, uint8 alpha);
  wchar_t* mLabel;
  Font* mFont;

  void RecalculateWordWrap();
  bool mWordWrap;
  vector<Line> mLines;
};

class Popup : public GUIControl
{
public:
  uint TextColor;
  uint Event1;
  uint Event2;

  Popup();
  virtual ~Popup();
  virtual uint Type() const { return 'popu'; }

  Popup& Set(wchar_t* text, uint ev1, uint ev2, wchar_t* but1, wchar_t* but2 = 0);

	void SetLabel(wchar_t* text);

  virtual void Show();
  virtual void Hide();

  static Image* BackgroundGFX;
  static Image* ButtonGFX;
  static Font* PopupFont;
protected:
  virtual void UpdateAt(int dt);

  EventBuffer mOwnEventBuffer;

  bool mTwoButtons;
  wchar_t* mText;
  wchar_t* mButton1Text;
  wchar_t* mButton2Text;

  GUIControl mBackground;
  Label mLabel;
  Button mButton1;
  Button mButton2;
};

class TextBox : public GUIControl
{
public:
  TextBox();
  virtual ~TextBox();
  virtual uint Type() const { return 'txtb'; }

  uint TextColor;
  std::wstring Text;
  int MarginLeft, MarginTop;
  int BoxWidth;

  TextBox& Set(Image& image, int x, int y, Font& font, int marginLeft = 0, int marginRight = 0, int boxWidth = -1);
  void SetFont(Font* font);
protected:
  virtual void UpdateAt(int dt);
  virtual uint DrawAt(int x, int y, uint8 alpha);
  virtual bool OnMouseUp(int x, int y);
  Font* mFont;
  int mCursorPos;
  int mDrawOffset;
  bool mCursorInside;
};


#endif